package cn.yqn.service.impl;

import cn.yqn.constants.RedisRegistConstant;
import cn.yqn.domain.MessageSms;
import cn.yqn.dto.RedisRegisterDto;
import cn.yqn.exception.GlobalCustomException;
import cn.yqn.enums.GlobalEnumCode;
import cn.yqn.properties.RegisterProperties;
import cn.yqn.service.IMessageSmsService;
import cn.yqn.service.IVerifyCodeService;
import cn.yqn.util.AssertUtil;
import cn.yqn.util.StrUtils;
import cn.yqn.util.VerifyCodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Autowired
    private IMessageSmsService iMessageSmsService;

    @Autowired
    private RegisterProperties registerProperties;

    // 图形验证码
    @Override
    public String getVerifyCode(String key) {
        // 判断前端图片验证码是否为相同
        if(StringUtils.isEmpty(key)){
            throw new RuntimeException("参数有误！");
        }
        // 使用StrUtils工具生成四位数字节码
        String randomString = StrUtils.getComplexRandomString(4);
        // 放入redis中设置三分种有效
        redisTemplate.opsForValue().set(key, randomString,3, TimeUnit.MINUTES);
        // 转换为base64字节码
        return VerifyCodeUtils.verifyCode(100, 40, randomString);
    }

    @Override
    public void sendSmsCode(String mobile) {
        Date date = new Date();
        // 断言参数为空
        AssertUtil.isPhone(mobile, GlobalEnumCode.PHONE_FORMAT_ERROR);
        // 参数格式校验，等儿优化
        // 图形验证码校验、手机号是否已被注册校验，黑名单校验@TODO
        // redis获取code  register:%S = register:电话号码
        String key = String.format(RedisRegistConstant.PHONE_REGISTER_PREFIX, mobile);
        Object redisCode = redisTemplate.opsForValue().get(key);
        // 判断code存在?
        String code = "";
        if (redisCode != null){
            // 拆分时间戳
            RedisRegisterDto redisRegisterDto = (RedisRegisterDto) redisCode;
            // 判断是否过了1分钟
            if ((date.getTime() - redisRegisterDto.getDateTime()) < registerProperties.getInterval()){
                // 提醒用户请勿频繁获取
                throw new GlobalCustomException(GlobalEnumCode.INTERVAL_ERROR);
            }
            code = redisRegisterDto.getCode();
        }else {
            // redis中没有数据,则直接发送验证码
            code = StrUtils.getRandomString(registerProperties.getCodesize());
        }
        // 保存信息,设置过期时间
        RedisRegisterDto redisVal = new RedisRegisterDto(code, date.getTime());
        redisTemplate.opsForValue().set(key, redisVal, registerProperties.getExpiration(), TimeUnit.MILLISECONDS);
        // 发送短息
        String hint = String.format(registerProperties.getSmshint(), code);
        // 打印记录
        System.out.println(hint);
        saveMessageSms(hint, date);
    }


    private void saveMessageSms(String hint, Date date) {
        // 记录smsMessage数据库
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle(registerProperties.getTitle());
        messageSms.setContent(hint);
        messageSms.setSendTime(date);
        // 设置IP
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        // 获取请求体 request
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        // 获取IP
        String remoteAddr = request.getRemoteAddr();
        messageSms.setIp(remoteAddr);
        iMessageSmsService.insert(messageSms);
    }
}

